package com.ztfgroup.supervise.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.hszsd.weixin.api.SmsAPI;
import com.hszsd.weixin.in.TextcardIn;
import com.hszsd.weixin.in.TextcardMessageIn;
import com.hszsd.weixin.out.GetUserInfoOut;
import com.ztfgroup.supervise.entity.Instruct;
import com.ztfgroup.supervise.entity.Message;
import com.ztfgroup.supervise.entity.User;
import com.ztfgroup.supervise.entity.vo.InstructVO;
import com.ztfgroup.supervise.mapper.InstructMapper;
import com.ztfgroup.supervise.mapper.MessageMapper;
import com.ztfgroup.supervise.mapper.UserMapper;
import com.ztfgroup.supervise.service.IInstructService;
import com.ztfgroup.supervise.service.IUserService;
import com.ztfgroup.supervise.util.Constants;
import com.ztfgroup.supervise.util.StringUtil;
import com.ztfgroup.supervise.wxparam.AccessTokenApi;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.text.StringEscapeUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import java.util.Date;
import java.util.List;

/**
 * <p>
 * 指示表 服务实现类
 * </p>
 *
 * @author hejr
 * @since 2019-03-06
 */
@Service
@Slf4j
public class InstructServiceImpl extends ServiceImpl<InstructMapper, Instruct> implements IInstructService {


    @Value("${supervise.agentId}")
    private Integer agentId;

    @Value("${supervise.corpId}")
    private String corpId;

    @Value("${supervise.corpSecret}")
    private String corpSecret;


    @Value("${supervise.domainHost}")
    private String domainHost;

    @Autowired
    private AccessTokenApi accessTokenApi;

    @Autowired
    private IUserService userService;

    @Autowired
    private MessageMapper messageMapper;

    @Autowired
    private UserMapper userMapper;

    @Override
    public List<InstructVO> findAllInstruct(String categoryId, String deptId, String userId, String dateType, Integer currentUserRoleId, String selfUserId) {
        String startTime = "";
        String endTime = "";
        if (StringUtils.isNotEmpty(dateType)) {
            if (dateType.equals(Constants.LAST_WEEK_TYPE)) {
                startTime = getBeforeDate(Constants.ONE_WEEK_DAY);
                endTime = Constants.DATE_FORMAT_SPECIAL_DAY.format(new Date());
            } else if (dateType.equals(Constants.LAST_MONTH_TYPE)) {
                startTime = getBeforeDate(Constants.ONE_MONTH_DAY);
                endTime = Constants.DATE_FORMAT_SPECIAL_DAY.format(new Date());
            } else if (dateType.equals(Constants.A_MONTH_AGO)) {
                endTime = getBeforeDate(Constants.ONE_MONTH_DAY);
            }
        }
        if (currentUserRoleId != null) {
            //非董事长角色，查询与自己相关的指示
            if (!currentUserRoleId.equals(Constants.LEADER_ROLE_ID)) {
                userId = selfUserId;
            }
        }
        List<InstructVO> instructVOList = baseMapper.findAllInstruct(categoryId, deptId, userId, startTime, endTime);
        return instructVOList;
    }

    @Override
    public Integer addInstruct(String categoryIds, String deptIds, String userIds, String content, String selfUserId) {
        log.info("新增指示，参数：categoryIds：{}，deptIds：{}，userIds：{}，content：{}，selfUserId：{}", categoryIds, deptIds, userIds, content, selfUserId);
        Integer ret = -1;
        Instruct instruct = new Instruct();
        instruct.setCategoryIds(categoryIds);
        instruct.setDeptIds(deptIds);
        instruct.setUserIds(userIds);
        instruct.setInstructContent(StringEscapeUtils.escapeHtml4(content));
        instruct.setTime(Constants.DATE_FORMAT_SPECIAL_DAY.format(new Date()));
        try {
            ret = baseMapper.addInstruct(instruct);
            if (ret > 0) {
                //获取选中的用户ID的微信号
                String wechatIds = "";
                if (StringUtils.isNotEmpty(userIds)) {
                    StringBuffer wechatUserIds = new StringBuffer();
                    List<User> userList = userMapper.findUserById(StringUtil.convertQueryIds(userIds));
                    if (userList != null && !userList.isEmpty()) {
                        for (User user : userList) {
                            wechatUserIds.append(user.getWxUserId()).append("|");
                        }
                        wechatIds = wechatUserIds.toString().substring(0, wechatUserIds.toString().length() - 1);
                    }
                }
                //得到当前新增的指示主键ID，用于微信推送时候需要
                String instructId = Constants.INSTRUCT_ID_PREX + instruct.getInstructId();
                StringBuffer wechatUserIds = new StringBuffer("");
                //选择了板块或者公司
                if (StringUtils.isNotEmpty(categoryIds) || StringUtils.isNotEmpty(deptIds)) {
                    List<User> userList = userService.findAllUser(categoryIds, deptIds);
                    if (userList != null && !userList.isEmpty()) {
                        for (User user : userList) {
                            //判断用户ID是否重复
                            if (StringUtils.isNotEmpty(wechatIds)) {
                                if (!wechatIds.contains(user.getWxUserId())) {
                                    wechatUserIds.append(user.getWxUserId()).append(Constants.LINE_SEPARATE_CHAR);
                                }
                            }
                        }
                    }
                }
                //选择了人员
                if (StringUtils.isNotEmpty(wechatIds)) {
                    wechatUserIds.append(wechatIds);
                }
                //如果有推送人员，则推送消息
                if (StringUtils.isNotEmpty(wechatUserIds)) {
                    Thread t = new Thread(new InstructClusterThread(wechatUserIds.toString(), instructId, selfUserId));
                    t.start();
                } else {
                    log.info("没有要推送的人员");
                }
            }
        } catch (Exception e) {
            log.error("新增指示异常, 异常信息：{}" + e.getMessage());
            e.printStackTrace();
        }
        return ret;
    }


    @Override
    public Boolean judgeIsScanInstruct(String selfUserId, String instructId) {
        log.info("判断当前用户是否有权限查看该指示，参数：userId：{}，instructId：{}", selfUserId, instructId);
        if (StringUtils.isEmpty(selfUserId) || StringUtils.isEmpty(instructId)) {
            log.info("用户ID或指示ID为空...");
            return false;
        }
        User user = userService.selectById(selfUserId);
        //如果当前用户的等级是1(董事长)，则无需权限判断
        if (user != null && user.getLv().equals(Constants.LEADER_ROLE_ID)) {
            return true;
        }
        Integer count = baseMapper.selectCount(new QueryWrapper<Instruct>().eq("INSTRUCT_ID", instructId).like("USER_IDS", selfUserId));
        return count > 0 ? true : false;
    }

    @Override
    public InstructVO findInstructAndUserNameById(String instructId) {
        return baseMapper.findInstructAndUserNameById(instructId);
    }

    /**
     * 推送董事长指示内部类
     */
    class InstructClusterThread implements Runnable {

        String userIds;
        String instructId;
        String selfUserId;

        public InstructClusterThread(String userIds, String instructId, String selfUserId) {
            this.userIds = userIds;
            this.instructId = instructId;
            this.selfUserId = selfUserId;
        }

        @Override
        public void run() {
            log.info("begin instruct push....");
            try {
                sendInstruct(userIds, instructId, selfUserId);
            } catch (Exception e) {
                log.error("instruct push is abnormal...");
            }
            log.info("instruct push is over...");
        }
    }

    /**
     * 指示消息推送
     *
     * @param userIds    待推送的微信用户ID
     * @param instructId 指示ID
     * @param selfUserId 推送人ID
     */
    private void sendInstruct(String userIds, String instructId, String selfUserId) {
        try {
            //当前时间
            String dateTime = Constants.DATE_FORMAT_SEND_TIME.format(new Date());
            //推送内容
            String description = Constants.INSTRUCT_MSG_TEMPLATE.replace("${dateTime}", dateTime);

            String accessToken = accessTokenApi.getAccessToken(corpId, corpSecret);
            TextcardMessageIn textcardMessageIn = new TextcardMessageIn();
            //设置推送用户ID
            textcardMessageIn.setTouser(userIds);
            textcardMessageIn.setAgentid(agentId);
            textcardMessageIn.setMsgtype("textcard");
            TextcardIn textcardIn = new TextcardIn();
            textcardIn.setBtntxt("详情");
            textcardIn.setTitle("董事长指示");
            textcardIn.setDescription(description);
            textcardIn.setUrl("http://" + domainHost + "/instructdetail?instructId=" + instructId);
            textcardMessageIn.setTextcard(textcardIn);
            GetUserInfoOut infoOut = SmsAPI.sendMessage(accessToken, textcardMessageIn);
            //往消息表中新增数据
            Message message = new Message();
            message.setId(Constants.MESSAGE_ID_PREX);
            message.setSendTime(Constants.DATE_FORMAT_SPECIAL_DAY.format(new Date()));
            message.setSender(selfUserId);
            message.setReceiver(userIds);
            message.setContent(description);
            message.setType("D");
            message.setStatus(String.valueOf(infoOut.getErrcode()));
            Integer ret = messageMapper.addMessage(message);
            log.info("指示消息入库" + (ret > 0 ? "成功" : "失败"));
        } catch (Exception e) {
            log.error("指示消息推送失败，userIds：{}", userIds);
            e.printStackTrace();
        }
    }

    /**
     * 获取指定天数之前的时间
     *
     * @param day
     * @return
     */
    private String getBeforeDate(int day) {
        Date yestDay = org.apache.commons.lang3.time.DateUtils.addDays(new Date(), -day);
        String today = Constants.DATE_FORMAT_SPECIAL_DAY.format(yestDay);
        return today;
    }

}
